package main

import (
	"bytes"
	"fmt"
	"html/template"
	"net/http"
	"net/smtp"
	"strconv"
	"time"
)

func dateFormat(layout string, d time.Time) string {
	return d.Format(layout)
}

var funcMap = template.FuncMap{
	"dateFormat": dateFormat,
}

type Page struct {
	Title, Content string
	HTMLContent    template.HTML
}

type User struct {
	Username, Name string
}

type Quote struct {
	Quote, Name string
}

var tmail *template.Template

var t *template.Template
var tm *template.Template
var ts map[string]*template.Template
var qc template.HTML

func init() {
	t = template.Must(template.ParseFiles("sample.html"))
	tm = template.Must(template.ParseFiles("mapp.html"))

	ts = make(map[string]*template.Template)
	temp := template.Must(template.ParseFiles("base.html", "user.html"))
	ts["user.html"] = temp
	temp = template.Must(template.ParseFiles("base.html", "page.html"))
	ts["page.html"] = temp

	tmail = template.New("email")
	tmail.Parse(emailTemplate)
}

func displayPage(w http.ResponseWriter, r *http.Request) {
	p := &Page{
		Title:   "An Example",
		Content: "Have fun stormin’ da castle.",
	}
	t.Execute(w, p)
}

var tpl = `<!DOCTYPE HTML>
			<html>
			<head>
			<meta charset="utf-8">
			<title>Date Example</title>
			</head>
			<body>
			<p>{{.Date | dateFormat "Jan 2, 2006"}}</p>
			</body>
			</html>`

//接卸字符串模版加载日期
func displayTpl(w http.ResponseWriter, r *http.Request) {
	t := template.New("date")
	t.Funcs(funcMap)
	t.Parse(tpl)
	data := struct{ Date time.Time }{
		Date: time.Now(),
	}
	t.Execute(w, data)
}

//实用缓冲区
func displayPageBuffer(w http.ResponseWriter, r *http.Request) {
	p := &Page{
		Title:   "An Example",
		Content: "Have fun stormin’ da castle.",
	}
	var b bytes.Buffer
	err := t.Execute(&b, p)
	if err != nil {
		fmt.Fprint(w, "A error occured.")
		return
	}
	b.WriteTo(w)
}

//多模版组合
func mixPage(w http.ResponseWriter, r *http.Request) {
	tt := template.Must(template.ParseFiles("mix.html", "head.html"))
	p := &Page{
		Title:   "An Example",
		Content: "Have fun stormin’ da castle.",
	}
	tt.ExecuteTemplate(w, "mix.html", p)
}

//模版继承
func displayPageInfo(w http.ResponseWriter, r *http.Request) {
	p := &Page{
		Title:   "An Example",
		Content: "Have fun stormin’ da castle.",
	}
	ts["page.html"].ExecuteTemplate(w, "base", p)
}

func displayUser(w http.ResponseWriter, r *http.Request) {
	u := &User{
		Username: "swordsmith",
		Name:     "Inigo Montoya",
	}
	ts["user.html"].ExecuteTemplate(w, "base", u)
}

func dataTypeMappingToTemplate(w http.ResponseWriter, r *http.Request) {
	q := &Quote{
		Quote: `You keep using that word. I do not thinkit means what you think it means.`,
		Name:  "Inigo Montoya",
	}
	var b bytes.Buffer
	t.ExecuteTemplate(&b, "quote.html", q)

	qc = template.HTML(b.String())
	p := &Page{
		Title:       "A User",
		HTMLContent: qc,
	}
	tm.ExecuteTemplate(w, "mapp.html", p)
}

func main() {
	rsEmail()
	http.HandleFunc("/", displayPage)
	http.HandleFunc("/tpl", displayTpl)
	http.HandleFunc("/buffer", displayPageBuffer)
	http.HandleFunc("/mix", mixPage) //多模版组合
	http.HandleFunc("/pageInfo", displayPageInfo)
	http.HandleFunc("/user", displayUser)
	http.HandleFunc("/mapping", dataTypeMappingToTemplate)
	http.ListenAndServe(":8080", nil)
}

type EmailMessage struct {
	From, Subject, Body string
	To                  []string
}
type EmailCredentials struct {
	Username, Password, Server string
	Port                       int
}

const emailTemplate = `From: {{.From}}
						To: {{.To}}
						Subject {{.Subject}}
						{{.Body}}
						`

func rsEmail() {
	message := &EmailMessage{
		From:    "me@example.com",
		To:      []string{"you@example.com"},
		Subject: "A test",
		Body:    "Just saying hi",
	}
	var body bytes.Buffer
	tmail.Execute(&body, message)

	authCreds := &EmailCredentials{
		Username: "myUsername",
		Password: "myPass",
		Server:   "smtp.example.com",
		Port:     25,
	}
	auth := smtp.PlainAuth("",
		authCreds.Username,
		authCreds.Password,
		authCreds.Server,
	)

	smtp.SendMail(authCreds.Server+":"+strconv.Itoa(authCreds.Port),
		auth,
		message.From,
		message.To,
		body.Bytes())
}
